﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;
using System.Runtime.CompilerServices;

namespace MrBrooks.Utility
{
    /// <summary>
    /// 日志工具
    /// </summary>
    public class LogsHelper
    {
        #region .Normal.
        // Fields
        private AutoResetEvent are = new AutoResetEvent(true);
        private bool isRunning = true;
        private Thread flushTimer;
        private StreamWriter writer;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="logName"></param>
        public LogsHelper(string logName)
        {
            string fileName = string.Format("{0} {1}.txt", DateTime.Now.ToString("dd-HH"), logName);

            string path = AppDomain.CurrentDomain.BaseDirectory + "log";
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }

            path = string.Format(@"{0}\{1}", path, DateTime.Now.ToString("yyyyMM"));
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }

            try
            {
                this.writer = new StreamWriter(path + @"\" + fileName);
            }
            catch (Exception ex)
            {
                throw ex;
            }

            if (this.flushTimer == null)
            {
                this.flushTimer = new Thread(new ThreadStart(this.FlushTimer));
                this.flushTimer.Start();
            }
        }

        /// <summary>
        /// 关闭
        /// </summary>
        public void Close()
        {
            this.isRunning = false;
            if (this.writer != null)
            {
                this.writer.Close();
                this.writer.Dispose();
            }
        }

        /// <summary>
        /// 定时将日志写入文件
        /// </summary>
        private void FlushTimer()
        {
            while (this.isRunning)
            {
                if (this.writer != null)
                {
                    this.are.WaitOne(10000);
                    this.writer.Flush();
                    this.are.Set();
                }

                Thread.Sleep(2000);
            }
        }

        /// <summary>
        /// 追加日志
        /// </summary>
        /// <param name="content"></param>
        public void Append(string content)
        {
            string info = "[" + DateTime.Now.ToString("MM-dd HH:mm:ss") + "] " + content;
            this.are.WaitOne(10000);
            this.writer.WriteLine(info);
            this.are.Set();
        }
        #endregion

        #region .Static.
        private static string lastLostName = string.Empty;

        private static StreamWriter lostWriter;
        private static StreamWriter logsWriter;

        /// <summary>
        /// 关闭
        /// </summary>
        private static void CloseLogsWriter()
        {
            if (logsWriter != null)
            {
                CurrentLogName = null;
                logsWriter.Close();
                logsWriter.Dispose();
                logsWriter = null;
            }
        }

        /// <summary>
        /// 关闭
        /// </summary>
        private static void CloseLostWriter()
        {
            if (lostWriter != null)
            {
                lastLostName = null;
                lostWriter.Close();
                lostWriter.Dispose();
                lostWriter = null;
            }
        }

        /// <summary>
        /// 追加日志(以日期-时间 文件名记录)
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="content"></param>
        public static void Append(string filename, string content)
        {
            Append(filename, content, true);
        }

        /// <summary>
        /// 追加日志信息
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="content"></param>
        /// <param name="nameByDay"></param>
        public static void Append(string filename, string content, bool nameByDay)
        {
            string fileName = nameByDay ? (DateTime.Now.ToString("dd-HH") + " " + filename + ".txt") : (filename + ".txt");
            string path = AppDomain.CurrentDomain.BaseDirectory + "log";
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }

            path = string.Format(@"{0}\{1}", path, DateTime.Now.ToString("yyyyMM"));
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }

            AppendLog(path, fileName, content);
        }

        /// <summary>
        /// 追加日志信息
        /// </summary>
        /// <param name="path">目录</param>
        /// <param name="filename">文件名</param>
        /// <param name="content">内容</param>
        private static void AppendLog(string path, string filename, string content)
        {
            string fullname = path + @"\" + filename;
            string info = "[" + DateTime.Now.ToString("MM-dd HH:mm:ss") + "] " + content + "\r\n";
            try
            {
                if (fullname != CurrentLogName)
                {
                    if (CurrentLogName != null)
                    {
                        CloseLogsWriter();
                    }

                    logsWriter = new StreamWriter(fullname, true, Encoding.UTF8);
                    CurrentLogName = fullname;
                }

                logsWriter.Write(info);
                logsWriter.Flush();
            }
            catch
            {
                AppendLostLog(path, content);
            }
        }

        /// <summary>
        /// 追加丢失的日志
        /// </summary>
        /// <param name="path"></param>
        /// <param name="content"></param>
        private static void AppendLostLog(string path, string content)
        {
            try
            {
                string fileName = string.Format(@"{0}\{1}_LostLog.txt", path, DateTime.Now.ToString("dd-HH"));
                if (fileName != lastLostName)
                {
                    CloseLostWriter();
                    lostWriter = new StreamWriter(fileName, true, Encoding.UTF8);
                }

                lastLostName = fileName;
                string text = string.Format("[{0}] {1} \r\n", DateTime.Now.ToString("MM-dd HH:mm:ss"), content);
                lostWriter.Write(text);
                lostWriter.Flush();
            }
            catch { }
        }

        /// <summary>
        /// 当前线程使用的文件名
        /// </summary>
        public static string CurrentLogName { get; private set; }
        #endregion
    }
}
